﻿#include "admin_log_in.h"
#include "ui_admin_log_in.h"
#include<QDebug>
#include<iostream>
#include<QString>
#include <QBitmap>
#include <QPainter>
#include"face.hpp"
#include"maininterface.h"

admin_log_in::admin_log_in(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::admin_log_in)
{

    ui->setupUi(this);
    //(1)设置时间



    //定义一个定时器，将这个定时器的timeout()信号和自己定义的函数进行绑定，如同在程序的主线程里面每隔一段时间执行一次自己定义的槽函数。
    timer.start(1000);
                   // timer->start(5000)开启定时器, //每隔5秒，定时器Timer自动触发timeout()每隔5秒执行一次自己的槽函数
    connect(&timer,&QTimer::timeout,this,&admin_log_in::run_time);//绑定定时器 timeout为定时器发出信号

    //把所有的数字键盘关联到同一槽函数
    connect(ui->pB1,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB2,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB3,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB4,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB5,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB6,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB7,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB8,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB9,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pBOK,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pB0,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(ui->pBDEL,&QPushButton::clicked,this,&admin_log_in::btclicked);
    connect(&timer_1,&QTimer::timeout,this,&admin_log_in::face_recognition);
    //加载opencv分类器
   cascade.load("G:\\haarcascade_frontalface_alt2.xml");
   model = face::FisherFaceRecognizer::create();
  //1.加载训练好的模型
   model->read("G:\\MyFaceFisherModel.xml");




    //(2)创建一个数据库
   QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE");
   //设置数据库名，指明路径
   db.setDatabaseName("G:\\Admin.db");
   if(!db.open())
   {
       qDebug()<<"open error";
       //cout<<"open false"<<endl;
   }
   //创建数据库表
   //创建管理员表
   //通过exec()成员函数来执行DML(数据操作语言)语句
   // PRIMARY KEY AUTOINCREMENT,":表示该列为整数递增,如果为空时则自动填入1
   //然后在下面的每一行都会自动+1, PRIMARY KEY则表示该列作为列表的主键,通过它可以轻易地获取某一行数据
   QSqlQuery query;
   query.exec("CREATE TABLE Admin("
  "id integer primary key autoincrement,"
  "name text not NULL,"
  "password text not NULL,"
  "level int  not NULL,"
  "label int  not NULL)" //创建一个Admin表,标题分别为id、name、press、level,label,not NULL表示该列不为空
              );


   //创建学生表
   QSqlQuery query1;
   query1.exec("CREATE TABLE Student("
"Id integer primary key autoincrement,"
"Number int  not NULL,"
"Name  text not NULL,"
"Sex text  not NULL,"
"Age int  not NULL)"
);

   //创建考勤打卡表
   QSqlQuery query2;
   query2.exec("CREATE TABLE Attenddence("
"id integer primary key autoincrement,"
"Sno int not NULL,"
"Time text not NULL,"
"level int  not NULL)"
);



   //创建通知表
   QSqlQuery query3;
   query3.exec("CREATE TABLE Inform("
 "id integer primary key autoincrement,"
 "Title int not NULL,"
 "Content text not NULL,"
  "Time int  not NULL)"
);




}

//槽信号响应 显示时间
void admin_log_in::run_time()
{
    QDateTime currenttime= QDateTime::currentDateTime();
    ui->label_3->setText(currenttime.toString("hh:mm:ss"));
    ui->label_4->setText(currenttime.toString("yyyy-MM-dd"));
    ui->label_5->setText(currenttime.toString("ddd"));
}



//按钮响应函数
//密码方式登录
void admin_log_in::btclicked()
{

    //获取信号发出者
    QPushButton *button=qobject_cast<QPushButton *>(sender());//通过sender()函数可以找到对于信号的发出者
    QString string =button->text();
    // qDebug()<<string;
    QString  passEdit=ui->passwordEdit->text();

    //qDebug()<<passEdit;     //开始是默认有个空字符串
    if(string!="DEL"&&string!="OK")
    {
        passEdit.append(string);
    }
    else if (string=="DEL")
    {
        passEdit.remove(passEdit.size()-1,1);
    }
    else if (string=="OK")
    {
        password=ui->passwordEdit->text();
        qDebug()<<"Your password is "<<password;
        checkpassword(password );
    }
   // qDebug()<<passEdit;
    ui->passwordEdit->setText(passEdit);

}


//检测密码是否正确
void admin_log_in::checkpassword(QString &password)
{

    QString sql=QString("select * from  Admin where password='%1'").arg(password);//选择出所有password=123的的行
    // qDebug()<<sql;
    QSqlQuery query(sql);
    bool b=query.next();//执行完一次next，他就指向下一元素，如果查询不到，返回false,若查询到，开始检索第一条记录
    if(!b)
    {
        QMessageBox::information(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("密码错误") );
    }


    while(b)//进行行遍历，输出所有密码正确的行的值·
    {

        qDebug()<<query.value(0).toInt()<<query.value(1).toString()<<query.value(2).toString()<<query.value(3).toString();
        qDebug()<<QString::fromLocal8Bit("密码正确！");
        b=query.next();
        MainInterface * w= new MainInterface();
        w->setWindowTitle(QString::fromLocal8Bit("主界面"));
        w->show();
        this->close();


    }
}

admin_log_in::~admin_log_in()
{
    delete ui;


    qDebug()<<"bbbbbbb";
}


//用人脸识别方式登录,点击响应
void admin_log_in::on_pBOpen_clicked()
{
    capture.open(0,cv::CAP_DSHOW);
    //cv::imshow("frame",frame);

    //定时器timer_1开启，每隔20ms触发timeout函数，执行face_recongniton函数
     capture.open(0,cv::CAP_DSHOW);
    timer_1.start(20);//定时器timer_1开启，触发信号

}

//从模型中返回人脸标签
int admin_log_in::Predict(Mat &image)
{
    Mat face_test;
    int predict = 0;
    //截取的ROI人脸尺寸调整
    if (image.rows >= 120)
    {
        //改变图像大小，使用双线性差值
      cv::resize(image, face_test, Size(92, 112));

    }
    //判断是否正确检测ROI
    if (!face_test.empty())
    {
        //测试图像应该是灰度图
        predict = model->predict(face_test);
    }

    return predict;
}


//定时器timer_1响应槽函数
void admin_log_in::face_recognition()
{

     //定时器开启，20ms触发一次，无需while
           capture >> frame;
           cvtColor(frame, gray, COLOR_RGB2GRAY);//测试图像必须为灰度图
           equalizeHist(gray, gray); //变换后的图像进行直方图均值化处理
           //检测人脸
           cascade.detectMultiScale(gray, faces,1.1, 4, CASCADE_DO_ROUGH_SEARCH, Size(30, 30), Size(500, 500));


           Mat face;
           Point text_lb;//文本写在的位置
           //框出人脸
             String str ;
  if(faces.size()==1)
{
           Mat  pImage_roi = gray(faces[0]); //将所有的脸部保存起来
           text_lb = Point(faces[0].x, faces[0].y);
           qDebug()<<"detection"<<detection<<"prediction"<<Predict(pImage_roi);
   if(detection==Predict(pImage_roi))
  {
           num++;
        if(num == 1 )//连续识别相同到n 次，可进入数据库查询
     {
      //根据编号查询数据库
       QString sql = QString("select * from Admin where label='%1'").arg(Predict(pImage_roi));
       QSqlQuery query(sql);

        while(query.next())
        {
        QString message = query.value(1).toString()+QString::fromLocal8Bit(",欢迎登录！");
        QMessageBox::about(this, QString::fromLocal8Bit("恭喜"),message);
         //str = "yq-c";
       MainInterface *w= new MainInterface(this);
     //将管理员名字传送过去
        w->setAdmin(query.value(1).toString());
        w->show();
        w->setWindowTitle(QString::fromLocal8Bit("主界面"));
        this->close();

        timer_1.stop();
        capture.release();
        //delete w;//看看释放内存的结果
        }
        num =0;
     }
  }
  else
       {
          num=0;//自己改
      }

  detection = Predict(pImage_roi);
        //绘制边角
      cv::line(frame,Point(faces[0].x, faces[0].y),Point(faces[0].x+60,faces[0].y),Scalar(0,0,255),4);
      cv::line(frame,Point(faces[0].x, faces[0].y),Point(faces[0].x,faces[0].y+40),Scalar(0,0,255),4);

      //cv::line(frame,Point(faces[i].x+faces[i].width-60, faces[i].y),Point(faces[i].x+faces[i].width,faces[i].y),Scalar(0,0,255),4);
      cv::line(frame,Point(faces[0].x+faces[0].width, faces[0].y),Point(faces[0].x+faces[0].width,faces[0].y+40),Scalar(0,0,255),4);


      cv::line(frame,Point(faces[0].x, faces[0].y+faces[0].height),Point(faces[0].x+60,faces[0].y+faces[0].height),Scalar(0,0,255),4);
      cv::line(frame,Point(faces[0].x, faces[0].y+faces[0].height-40),Point(faces[0].x,faces[0].y+faces[0].height),Scalar(0,0,255),4);

      cv::line(frame,Point(faces[0].x+faces[0].width-60, faces[0].y+faces[0].height),Point(faces[0].x+faces[0].width,faces[0].y+faces[0].height),Scalar(0,0,255),4);
      cv::line(frame,Point(faces[0].x+faces[0].width, faces[0].y+faces[0].height-40),Point(faces[0].x+faces[0].width,faces[0].y+faces[0].height),Scalar(0,0,255),4);

     //绘制的图片，利用对角线绘制图形 颜色 线条宽度
     // rectangle(frame, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(255,255,255), 2, 8);//放入缓存

     // putText(frame, str, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255),2);//添加文字

 }
           cvtColor(frame,frame,COLOR_BGR2RGB);
           //根据图像宽高来构造图像,用QImage来处理数据
           QImage image(frame.data, frame.cols, frame.rows, frame.step1() , QImage::Format_RGB888);//存入格式为R, G, B 对应 0,1,2
           QPixmap pixmap = QPixmap::fromImage(image);//利用 QImage（独立硬件，存储客户端） 的数据填充 QPixmap(依赖于硬件),来显示图像，可以加速显示
           pixmap = pixmap.scaled(ui->label_face->size());//图像缩放，自适应Label大小
           //mmp =  PixmapToRound(mmp, 148);
           ui->label_face->setPixmap(pixmap);
 }


